package xyz.renyumeng.xkm.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import xyz.renyumeng.xkm.client.es.EsShopFeignClient;
import xyz.renyumeng.xkm.dto.base.SearchPage;
import xyz.renyumeng.xkm.dto.shop.ProductInfoDto;
import xyz.renyumeng.xkm.exception.XkmException;
import xyz.renyumeng.xkm.model.es.EsProduct;
import xyz.renyumeng.xkm.model.shop.ProductInfo;
import xyz.renyumeng.xkm.model.shop.ProductTypeInfo;
import xyz.renyumeng.xkm.result.Result;
import xyz.renyumeng.xkm.shop.mapper.ProductMapper;
import xyz.renyumeng.xkm.shop.service.ProductTypeInfoService;
import xyz.renyumeng.xkm.shop.service.UserProductService;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.*;

import static xyz.renyumeng.xkm.rabbitMQ.RabbitMqConstant.*;

/**
 * @author renyumeng
 * @date Created in 20:51 2023/7/2
 */
@Slf4j
@Service
@Transactional
public class UserProductServiceImpl extends ServiceImpl<ProductMapper, ProductInfo> implements UserProductService {
    @Resource
    private EsShopFeignClient esShopFeignClient;

    @Resource
    private ProductTypeInfoService productTypeInfoService;

    @Resource
    private RabbitTemplate rabbitTemplate;


    @Override
    public Result<Object> listedProduct(Long productId, Integer isListed) {
        LambdaUpdateWrapper<ProductInfo> productInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        productInfoLambdaUpdateWrapper
                .set(ProductInfo::getIsListed, isListed)
                .eq(ProductInfo::getId, productId);
        boolean update = this.update(productInfoLambdaUpdateWrapper);
        if (!update) {
            throw new XkmException(201, "修改商品上架信息失败!");
        }
        ES_PERSISTENCE_EXECUTOR.submit(() -> {
            this.sendMessage2EsService2Update(productId, isListed);
        });
        return Result.ok(null).message("修改成功!");
    }

    private void sendMessage2EsService2Update(Long productId, Integer isListed) {
        ProductInfo productInfo = this.getById(productId);
        if (!ObjectUtils.isEmpty(isListed)) {
            productInfo.setIsListed(isListed);
        }

        EsProduct esProduct = BeanUtil.copyProperties(productInfo, EsProduct.class);
        esProduct.setProductDesc(productInfo.getDesc());

        ProductTypeInfo productTypeInfo = productTypeInfoService.getById(esProduct.getTypeId());

        if (ObjectUtils.isEmpty(productTypeInfo)) {
            throw new XkmException(201, "该商品的类型不存在!");
        }
        esProduct.setType(productTypeInfo.getType());

        rabbitTemplate.convertAndSend(ES_PRODUCT_EXCHANGE, ES_PRODUCT_UPDATE_KEY, esProduct);


    }

    @Override
    public Result<SearchPage<List<EsProduct>>> pageProductIInfoWithFilter(Integer current, Integer size, String filter) {
        SearchPage<List<EsProduct>> listSearchPage = esShopFeignClient.pageWithFilter(current, size, filter);
        if (ObjectUtils.isEmpty(listSearchPage)) {
            throw new XkmException(201, "es服务异常!");
        }

        return Result.ok(listSearchPage);
    }

    @Override
    public Result<Object> addProductInfo(ProductInfoDto productInfoDto) {
        ProductInfo productInfo = BeanUtil.copyProperties(productInfoDto, ProductInfo.class);
        boolean isSaved = this.save(productInfo);
        if (BooleanUtil.isFalse(isSaved)) {
            throw new XkmException(201, "新增商品信息失败!");
        }
        ES_PERSISTENCE_EXECUTOR.submit(() -> this.sendMessage2EsService2Add(productInfo, ES_PRODUCT_INSERT_KEY));
        return Result.ok(null).message("新增商品信息成功!");
    }

    @Override
    public Result<Object> upDateProduct(ProductInfoDto productInfoDto) {
        ProductInfo productInfo = BeanUtil.copyProperties(productInfoDto, ProductInfo.class);
        boolean isSaved = this.updateById(productInfo);
        log.info("修改后的productInfo={}", productInfo);
        if (BooleanUtil.isFalse(isSaved)) {
            throw new XkmException(201, "修改的商品信息不存在!");
        }
        Long productId = productInfo.getId();
        ES_PERSISTENCE_EXECUTOR.submit(() ->
                this.sendMessage2EsService2Update(productId, null)
        );
        return Result.ok(null).message("修改商品信息成功!");
    }

    @Override
    public Result<Object> deleteProductById(Long productId) {
        boolean isRemoved = this.removeById(productId);
        if (!isRemoved) {
            throw new XkmException(201, "删除失败!");
        }
        rabbitTemplate.convertAndSend(ES_PRODUCT_EXCHANGE, ES_PRODUCT_DELETE_KEY, productId);
        return Result.ok(null).message("删除成功!");
    }

    @Override
    public Result<EsProduct> getProductById(Long productId) {
        EsProduct esProduct = esShopFeignClient.getEsProductById(productId);
        if (ObjectUtils.isEmpty(esProduct)) {
            throw new XkmException(201, "商品信息不存在!");
        }
        return Result.ok(esProduct).message("查询成功!");
    }

    @Override
    public Result<SearchPage<List<EsProduct>>> getProductListByOwnerId(Long ownerId, Integer page, Integer size) {
        SearchPage<List<EsProduct>> listSearchPage = esShopFeignClient.pageByOwnerId(page, size, ownerId);
        return Result.ok(listSearchPage).message("查询成功!");
    }

    @Override
    public Result<SearchPage<List<EsProduct>>> getProductIsSoleListByOwnerId(Long ownerId, Integer page, Integer size) {
        SearchPage<List<EsProduct>> listSearchPage = esShopFeignClient.pageByOwnerIdIsSole(page, size, ownerId, 1);
        return Result.ok(listSearchPage).message("查询成功!");
    }


    private void sendMessage2EsService2Add(ProductInfo productInfo, String key) {
        EsProduct esProduct = BeanUtil.copyProperties(productInfo, EsProduct.class);
        ProductTypeInfo typeInfo = productTypeInfoService.getById(esProduct.getTypeId());
        if (ObjectUtils.isEmpty(typeInfo)) {
            throw new XkmException(201, "用户选择的类型不存在!");
        }

        esProduct.setType(typeInfo.getType());
        esProduct.setProductDesc(productInfo.getDesc());
        esProduct.setId(productInfo.getId());
        esProduct.setIsListed(0);
        esProduct.setIsSoled(0);

        log.info("消息的对象={}", esProduct);
        rabbitTemplate.convertAndSend(ES_PRODUCT_EXCHANGE, key, esProduct);
    }

    private static final ExecutorService ES_PERSISTENCE_EXECUTOR = new ThreadPoolExecutor(
            10,
            15,
            3,
            TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(3),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.DiscardOldestPolicy());
}
